module ratio_calcu_top(
		//时钟&复位
		input   wire			resetb,
		input   wire			sclk,
		
		//设置数据
		input	wire			set_clk,
		input	wire			set_d_ok,
		input	wire    [23:0]  set_addr,
		input	wire    [7:0]   set_data,
		
		input	wire	[11:0]	p_width,
		
		//调整数据输入
		input	wire			BL_clk,
		input	wire			BL_we,
(* MARK_DEBUG="true" *)			input	wire	[12:0]	BL_waddr,
(* MARK_DEBUG="true" *)			input	wire	[8:0]	BL_wdata,
		input	wire			BL_we_end,
		input	wire			lock,
				
		//输出时序
		input	wire			vs,
		input	wire			de,

		//调整数据
(* MARK_DEBUG="true" *) 		output	wire			adj_buf_sel,
(* MARK_DEBUG="true" *) 		output	wire			adj_wen,
(* MARK_DEBUG="true" *) 		output	wire    [15:0]	adj_w_data,
		
		//调试信号
		output	wire    [47:0]   tout
		);

//***********************************************/
//				参数定义
//***********************************************/
parameter       Read_IDLE	=4'b0001;
parameter       Read_Pre	=4'b0010;
parameter       Read_Next	=4'b0100;
parameter       Read_Wait	=4'b1000;

parameter       CALC_CORE_NUM	= 1;

//***********************************************/
//				信号定义
/************************************************/
reg				h_map_we, l_map_we;
wire	[15:0]	h_map_data;
reg		[9:0]	l_map_addr;
wire	[63:0]	l_map_data;

reg		[15:0]	l_rdata;
wire			l_b_last;
reg		[6:0]	h_offset;

reg		[3:0]	read_state;
reg		[7:0]	vs_t, de_t;
(* MARK_DEBUG="true" *) reg		[11:0]	h_count;
(* MARK_DEBUG="true" *) reg		[11:0]	l_count, l_max;
(* MARK_DEBUG="true" *) reg		[6:0]	h_block, l_block, l_block_cnt, l_block_max;
(* MARK_DEBUG="true" *) reg				v_start, h_start, h_l_end, h_l_block_end;

reg				adj_en, l_load_first, l_load_flag;
reg		[5:0]	load_first_t, load_flag_t;
(* MARK_DEBUG="true" *) reg		[71:0]	bl_l0_d, bl_l1_d, bl_l2_d, bl_l3_d, bl_l4_d, bl_l5_d, bl_l6_d, bl_l7_d, bl_l8_d;
(* MARK_DEBUG="true" *) wire	[71:0]	bl_data;

(* MARK_DEBUG="true" *) reg		[19:0]	adj_flag;

wire	[31:0]	tout_a;

/************************************************/
//      		背光数据缓冲
/************************************************/
bl_data_buf bl_data_buf(
		//时钟&复位
		.resetb		(resetb),
		.sclk		(sclk),

		//设置数据
		.set_clk	(set_clk),
		.set_d_ok	(set_d_ok),
		.set_addr	(set_addr),
		.set_data	(set_data),
		
		//背光数据
    	.BL_clk		(BL_clk),
		.BL_we		(BL_we),
		.BL_waddr	(BL_waddr),
		.BL_wdata	(BL_wdata),
		.BL_we_end	(BL_we_end),
		.lock		(lock),

		//数据读取
    	.v_start	(v_start),
		.bl_h_addr	(h_block),
		.bl_l_addr	(l_block),

		//调整数据
		.bl_data	(bl_data),
		
		//调试信号
		.tout		()
		);

/************************************************/
//				光场计算
/************************************************/
ratio_calc_04 ratio_calc(
		//时钟&复位
		.resetb(resetb),
		.sclk(sclk),
		
		//设置数据
		.set_clk(set_clk),
		.set_d_ok(set_d_ok),
		.set_addr(set_addr),
		.set_data(set_data),

		//背光数据
		.bl_l0_data(bl_l0_d),
		.bl_l1_data(bl_l1_d),
		.bl_l2_data(bl_l2_d),
		.bl_l3_data(bl_l3_d),
		.bl_l4_data(bl_l4_d),
		.bl_l5_data(bl_l5_d),
		.bl_l6_data(bl_l6_d),
		.bl_l7_data(bl_l7_d),
		.bl_l8_data(bl_l8_d),
		.bl_l9_data(bl_data),
		
		//像素地址
		.adj_flag(adj_flag[0]),
		.h_offset(h_offset),
		.l_offset(l_rdata[14:8]),
		.l_new(1'b0),

        //结果输出
		.adjust_o(adj_w_data[15:0]),
		
		//调试信号
		.tout()
		);

//*************************************************/
//		分区位置缓冲
//*************************************************/	
//行分区缓儿 h_addr_map.coe
swsr_8kw8_4kr16_sdp_hbuf	h_locate_map(
	.clka	(set_clk),
	.ena	(1'b1),
	.wea	(h_map_we),
	.addra	(set_addr[12:0]),
	.dina	(set_data),
	
	.clkb	(sclk),
	.enb	(1'b1),
	.addrb	({1'b0, h_count[11:1]}), //两行用同相同配置
	.doutb	(h_map_data)
	);

//列分区缓儿  l_addr_map.coe
swsr_8kw8_1kr64_sdp_lbuf	l_locate_map(
	.clka	(set_clk),
	.ena	(1'b1),
	.wea	(l_map_we),
	.addra	(set_addr[12:0]),
	.dina	(set_data),
	
	.clkb	(sclk),
	.enb	(1'b1),
	.addrb	(l_map_addr),
	.doutb	(l_map_data)
	);

/************************************************/
//      参数配置
/************************************************/
always@(posedge set_clk or negedge resetb)
	if (resetb == 0) begin
		l_block_max <= 63;
		end
    else if  (set_d_ok == 1)
       case (set_addr[23:0])
            24'h001108:	l_block_max[6:0] <= set_data[6:0];
       endcase
	
always @(posedge sclk)
	l_max = p_width[11:1] - 2;
	
always @(posedge set_clk)
	if ((set_d_ok == 1) && (set_addr[23:13] == 11'b0000_0000_100))
		h_map_we <= 1;
	else
		h_map_we <= 0;
	
always @(posedge set_clk)
	if ((set_d_ok == 1) && (set_addr[23:13] == 11'b0000_0000_101))
		l_map_we <= 1;
	else
		l_map_we <= 0;
	
/************************************************/
//      读控冿
/************************************************/
//读状态机
always @(posedge sclk or negedge resetb)
	if (resetb == 0)
		read_state <= Read_IDLE;
	else
		case (read_state)
			Read_IDLE:	
				if ((v_start == 1) || (h_start == 1))
					read_state <= Read_Pre;
				
			Read_Pre:	
				if (l_block_cnt == 4)
					read_state <= Read_Next;
					
			Read_Next:
				if (h_l_end == 1)
					read_state <= Read_IDLE;
			
			default:
					read_state <= Read_IDLE;

		endcase

//信号延时
always @(posedge sclk) begin
	vs_t <= {vs_t[6:0], vs};
	de_t <= {de_t[6:0], de};
end

//行计数，DE上升沿+1
always @(posedge sclk)
	if (vs_t[3:2] == 2'b01)
		h_count <= 0;
	else if (de_t[3:2] == 2'b01)
		h_count <= h_count + 1;
		
//帧上升沿启动计算
always @(posedge sclk)
	if (vs_t[5:4] == 2'b01)
		v_start <= 1;
	else
		v_start <= 0;

//偶数行上升沿启动计算
always @(posedge sclk)
	if ((de_t[5:4] == 2'b01) && (h_count[0] == 0))
		h_start <= 1;
	else
		h_start <= 0;

//列计数
always @(posedge sclk)
	if (read_state != Read_Next)
		l_count <= 0;
	else
		l_count <= l_count + 1;
		
//列结束
always @(posedge sclk)
	if (read_state != Read_Next)
		h_l_end <= 0;
	else if (l_count == l_max)
		h_l_end <= 1;
	else
		h_l_end <= 0;
		
//读列块计数
always @(posedge sclk)
	if (read_state == Read_IDLE)
		l_block_cnt <= 0;
	else if ((read_state == Read_Pre) || ((l_b_last == 1) && (h_l_block_end == 0)))
		l_block_cnt <= l_block_cnt + 1;
		
//列块地址结束
always @(posedge sclk)
	if (l_block_cnt == l_block_max)
		h_l_block_end <= 1;
	else
		h_l_block_end <= 0;
		
//读列块地址
always @( * )
	l_block <= l_block_cnt;

//调整使能
always @(posedge sclk)
	if (read_state == Read_Next)
		adj_en <= 1;
	else
		adj_en <= 0;
		
/************************************************/
//				列分区映射表数据
/************************************************/
//映射表地址
reg		[1:0]	d_sel;

always @( * )
	l_map_addr <= l_count[11:2];
		
//always @(posedge sclk)
always @(posedge sclk)
	d_sel  <= l_count[1:0];
	
//映射表数据选通
//always @( * )
always @(posedge sclk)
	case (d_sel)
		0:	l_rdata <= l_map_data[15:0];
		1:	l_rdata <= l_map_data[31:16];
		2:	l_rdata <= l_map_data[47:32];
		3:	l_rdata <= l_map_data[63:48];
	endcase
		
//分区结束
assign	l_b_last = l_rdata[15];

/************************************************/
//				行分区映射表数据
/************************************************/
//行分区号
always @(posedge sclk)
	h_block <= h_map_data[6:0];
	
//行分区内偏移
always @(posedge sclk)
	h_offset <= h_map_data[14:8];
	
/************************************************/
//				背光数据加载
/************************************************/
always @(posedge sclk)
	if ((read_state == Read_Pre) && (l_block_cnt == 0))
		l_load_first <= 1;
	else
		l_load_first <= 0;

always @(posedge sclk)
	if ((read_state == Read_Pre) || (l_b_last == 1))
		l_load_flag <= 1;
	else
		l_load_flag <= 0;
		
always @(posedge sclk) begin
	load_first_t <= {load_first_t[4:0], l_load_first};
	load_flag_t <= {load_flag_t[4:0], l_load_flag};
	end

always @(posedge sclk)
	if (load_first_t[1] == 1) begin
		bl_l8_d <= bl_data;
		bl_l7_d <= bl_data;
		bl_l6_d <= bl_data;
		bl_l5_d <= bl_data;
		bl_l4_d <= bl_data;
		end
	else if (load_flag_t[1] == 1) begin
		bl_l8_d <= bl_data;
		bl_l7_d <= bl_l8_d;
		bl_l6_d <= bl_l7_d;
		bl_l5_d <= bl_l6_d;
		bl_l4_d <= bl_l5_d;
		bl_l3_d <= bl_l4_d;
		bl_l2_d <= bl_l3_d;
		bl_l1_d <= bl_l2_d;
		bl_l0_d <= bl_l1_d;
		end

//***************************************************
//				输出结果
//***************************************************
//输出同步延时
always @(posedge sclk)
	adj_flag <= {adj_flag[18:0], adj_en};
	
//输出缓冲区帧选择
assign	adj_buf_sel = h_count[1];
	
//输出使能
assign	adj_wen = adj_flag[15];
		
//***************************************************
//				调试信号
//***************************************************
assign	tout = {tout_a[25:0], h_count};

endmodule       
